<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>go[3]-接口 | Abel&#39;Blog</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="概述 包含nil指针的接口不是nil接口 类型断言 一些建议 使用golang组合时常犯的错 引用  概述接口是对类型行为的抽象和概括。接口抽象的方法可以让我们函数更加灵活和适应性。中间只定义了函数类型。接口就是约定。 接口本事存储数据内容为：  type: xxxvalue: xxx  定义实例 1234type interfaceName interface &amp;#123;     Write">
<meta property="og:type" content="article">
<meta property="og:title" content="go[3]-接口">
<meta property="og:url" content="http://example.com/2020/11/18/2020/2020-11-18-go[3]-%E6%8E%A5%E5%8F%A3/index.html">
<meta property="og:site_name" content="Abel&#39;Blog">
<meta property="og:description" content="概述 包含nil指针的接口不是nil接口 类型断言 一些建议 使用golang组合时常犯的错 引用  概述接口是对类型行为的抽象和概括。接口抽象的方法可以让我们函数更加灵活和适应性。中间只定义了函数类型。接口就是约定。 接口本事存储数据内容为：  type: xxxvalue: xxx  定义实例 1234type interfaceName interface &amp;#123;     Write">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://s3.ax1x.com/2021/02/18/yRbZk9.png">
<meta property="og:image" content="https://s3.ax1x.com/2021/02/18/yRbeYR.png">
<meta property="article:published_time" content="2020-11-17T16:00:00.000Z">
<meta property="article:modified_time" content="2021-07-28T09:12:59.007Z">
<meta property="article:author" content="Abel Sean">
<meta property="article:tag" content="golang">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://s3.ax1x.com/2021/02/18/yRbZk9.png">
  
    <link rel="alternate" href="/atom.xml" title="Abel&#39;Blog" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="/css/style.css">

<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">Abel&#39;Blog</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://example.com"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main"><article id="post-2020/2020-11-18-go[3]-接口" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2020/11/18/2020/2020-11-18-go%5B3%5D-%E6%8E%A5%E5%8F%A3/" class="article-date">
  <time datetime="2020-11-17T16:00:00.000Z" itemprop="datePublished">2020-11-18</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      go[3]-接口
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <ul>
<li><a href="#%E6%A6%82%E8%BF%B0">概述</a></li>
<li><a href="#%E5%8C%85%E5%90%ABnil%E6%8C%87%E9%92%88%E7%9A%84%E6%8E%A5%E5%8F%A3%E4%B8%8D%E6%98%AFnil%E6%8E%A5%E5%8F%A3">包含nil指针的接口不是nil接口</a></li>
<li><a href="#%E7%B1%BB%E5%9E%8B%E6%96%AD%E8%A8%80">类型断言</a></li>
<li><a href="#%E4%B8%80%E4%BA%9B%E5%BB%BA%E8%AE%AE">一些建议</a></li>
<li><a href="#%E4%BD%BF%E7%94%A8golang%E7%BB%84%E5%90%88%E6%97%B6%E5%B8%B8%E7%8A%AF%E7%9A%84%E9%94%99">使用golang组合时常犯的错</a></li>
<li><a href="#%E5%BC%95%E7%94%A8">引用</a></li>
</ul>
<h1 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h1><p>接口是对类型行为的抽象和概括。接口抽象的方法可以让我们函数更加灵活和适应性。中间只定义了函数类型。接口就是约定。</p>
<p>接口本事存储数据内容为：</p>
<blockquote>
<p>type: xxx<br>value: xxx</p>
</blockquote>
<p>定义实例</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> interfaceName <span class="keyword">interface</span> &#123;</span><br><span class="line">     Write([]<span class="keyword">byte</span>)</span><br><span class="line">     Read([]<span class="keyword">byte</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="包含nil指针的接口不是nil接口"><a href="#包含nil指针的接口不是nil接口" class="headerlink" title="包含nil指针的接口不是nil接口"></a>包含nil指针的接口不是nil接口</h1><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"> <span class="keyword">var</span> buf *bytes.Buffer</span><br><span class="line"> f(buf)</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">f</span><span class="params">(out io.Writer)</span></span> &#123;</span><br><span class="line">  <span class="keyword">if</span> out != <span class="literal">nil</span> &#123;</span><br><span class="line">     out.Write([]<span class="keyword">byte</span>(<span class="string">&quot;done!\n&quot;</span>))</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>虽然已经对out做了空的判断，但是依然会崩溃。原因是这个调用f函数的时候，给了一个空的*bytes.Buffer指针。所以接口本身不是空。</p>
<h1 id="类型断言"><a href="#类型断言" class="headerlink" title="类型断言"></a>类型断言</h1><p>x为一个interface，T为一个定义的类型。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> w io.Writer</span><br><span class="line">w = os.Stdout</span><br><span class="line">f := w.(*os.File) <span class="comment">// success</span></span><br><span class="line">e := w.(*bytes.Buffer) <span class="comment">// panic</span></span><br></pre></td></tr></table></figure>

<p>如果转换失败了，将会直接造成panic。如果断言操作的对象是一个nil接口，无论被断言成什么类型都会失败。</p>
<p>使用两个返回值方式的，第二个参数将会返回是否转换成功。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">b,ok :=w.(*bytes.Buffer)</span><br></pre></td></tr></table></figure>

<p>我们可以拿着ok变量来做逻辑。</p>
<p>对于类型的switch case语句可以这样来编写</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">sqlQuote</span><span class="params">(x <span class="keyword">interface</span>&#123;&#125;)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">switch</span> x:=x.(<span class="keyword">type</span>) &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="literal">nil</span>:</span><br><span class="line">         <span class="keyword">return</span> <span class="string">&quot;NULL&quot;</span></span><br><span class="line">    <span class="keyword">case</span> <span class="keyword">int</span>,<span class="keyword">uint</span>:</span><br><span class="line">         <span class="keyword">return</span> fmt.Sprintf(<span class="string">&quot;%d&quot;</span>,x)</span><br><span class="line">   <span class="keyword">default</span>:</span><br><span class="line">        <span class="built_in">panic</span>(fmt.Sprintf(<span class="string">&quot;unexpected type: %T: %v&quot;</span>,x,x))</span><br></pre></td></tr></table></figure>

<h1 id="一些建议"><a href="#一些建议" class="headerlink" title="一些建议"></a>一些建议</h1><p>设计一个新的包时，先创建一个接口的集合开始，后面定义满足它们具体的类型。每个接口都实现一个。请不要这么做，这种接口是不必要去抽象。只有两个或者以上的具体类型必须以相同的方法进行处理时候才需要。ask only for what you need.（奥卡姆剃刀）</p>
<h1 id="使用golang组合时常犯的错"><a href="#使用golang组合时常犯的错" class="headerlink" title="使用golang组合时常犯的错"></a>使用golang组合时常犯的错</h1><p>类关系：</p>
<p><a target="_blank" rel="noopener" href="https://imgchr.com/i/yRbZk9"><img src="https://s3.ax1x.com/2021/02/18/yRbZk9.png" alt="yRbZk9.png"></a></p>
<p>当有一个B类，转换成InterfaceA提供给外部。</p>
<p>外部直接调用FunA。</p>
<p>classA类里面实现的FunA方法调用了FunB，这个时候将会造成问题。</p>
<p>当函数调到FunA的时候，就进入了classA类中了，调用了classA.FunB函数，而不是调用classB.FunB函数。</p>
<p>有些人为了解决这个问题，直接将FunA参数表里面增加一个InterfaceA的原始指针。</p>
<p>这种情况下，最好是对外的函数不要互相调用</p>
<p><a target="_blank" rel="noopener" href="https://github.com/swordhell/learn_go/tree/master/learn_interface">测试源码</a></p>
<p>可以按照下面的方式来实现这个结构：</p>
<p><a target="_blank" rel="noopener" href="https://imgchr.com/i/yRbeYR"><img src="https://s3.ax1x.com/2021/02/18/yRbeYR.png" alt="yRbeYR.png"></a></p>
<p>对外部提供的接口 IMain 。</p>
<p>内部实现时 ISub ， IMain 聚合了 ISub ，而且比 ISub 多了一些公开的函数。</p>
<p>Main类里面没有任何的成员变量，是对工作流程的一种调配，不实现任何具体的功能。它内部聚合的 ISub 的实现，都依赖于 CSpecA，CSpecB。</p>
<p>CBase类有成员变量，在这块实现具体的功能。在CSpecA中直接可以将CBase类已经实现的函数，做特例化修改。</p>
<p>这样将会让程序更加的干净。</p>
<h1 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h1><ul>
<li>[1] <a target="_blank" rel="noopener" href="https://www.cnblogs.com/itplay/p/10671715.html">uml绘图</a></li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://example.com/2020/11/18/2020/2020-11-18-go[3]-%E6%8E%A5%E5%8F%A3/" data-id="ckrn3an75000v20xw4zyf71dr" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/golang/" rel="tag">golang</a></li></ul>

    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2020/11/18/2020/2020-11-18-FSM-Golang/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          FSM-golang
        
      </div>
    </a>
  
  
    <a href="/2020/11/18/2020/2020-11-18-go%5B4%5D-gogrutines/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">go[4]-goroutine</div>
    </a>
  
</nav>

  
</article>

</section>
        
          <aside id="sidebar">
  
    

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/3D/" rel="tag">3D</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/AI/" rel="tag">AI</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/C/" rel="tag">C++</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Game/" rel="tag">Game</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Go/" rel="tag">Go</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Linux/" rel="tag">Linux</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Math/" rel="tag">Math</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Server/" rel="tag">Server</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Unreal-Engine4/" rel="tag">Unreal Engine4</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git/" rel="tag">git</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/golang/" rel="tag">golang</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/guitar/" rel="tag">guitar</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/node-js/" rel="tag">node.js</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/protobuf/" rel="tag">protobuf</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/python/" rel="tag">python</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/recast/" rel="tag">recast</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/redis/" rel="tag">redis</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/type/" rel="tag">type</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vscode/" rel="tag">vscode</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%BF%90%E7%BB%B4/" rel="tag">运维</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/3D/" style="font-size: 10px;">3D</a> <a href="/tags/AI/" style="font-size: 11.67px;">AI</a> <a href="/tags/C/" style="font-size: 15px;">C++</a> <a href="/tags/Game/" style="font-size: 18.33px;">Game</a> <a href="/tags/Go/" style="font-size: 13.33px;">Go</a> <a href="/tags/Linux/" style="font-size: 13.33px;">Linux</a> <a href="/tags/Math/" style="font-size: 11.67px;">Math</a> <a href="/tags/Server/" style="font-size: 16.67px;">Server</a> <a href="/tags/Unreal-Engine4/" style="font-size: 10px;">Unreal Engine4</a> <a href="/tags/git/" style="font-size: 10px;">git</a> <a href="/tags/golang/" style="font-size: 20px;">golang</a> <a href="/tags/guitar/" style="font-size: 10px;">guitar</a> <a href="/tags/node-js/" style="font-size: 10px;">node.js</a> <a href="/tags/protobuf/" style="font-size: 10px;">protobuf</a> <a href="/tags/python/" style="font-size: 10px;">python</a> <a href="/tags/recast/" style="font-size: 11.67px;">recast</a> <a href="/tags/redis/" style="font-size: 10px;">redis</a> <a href="/tags/type/" style="font-size: 10px;">type</a> <a href="/tags/vscode/" style="font-size: 10px;">vscode</a> <a href="/tags/%E8%BF%90%E7%BB%B4/" style="font-size: 16.67px;">运维</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/07/">July 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/06/">June 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/04/">April 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/03/">March 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/01/">January 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/12/">December 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/11/">November 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/03/">March 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/11/">November 2018</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2021/07/19/2021/2021-07-19-etcd-learn/">go-etcd阅读笔记</a>
          </li>
        
          <li>
            <a href="/2021/07/19/2021/2021-07-19-socketop-learn/">REUSEPORT-REUSEADDR-学习</a>
          </li>
        
          <li>
            <a href="/2021/06/22/2021/2021-06-22-go-ethereum-learn/">go-ethereum阅读笔记</a>
          </li>
        
          <li>
            <a href="/2021/06/21/2021/2021-06-21-server%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/">server测试工具</a>
          </li>
        
          <li>
            <a href="/2021/06/09/2021/2021-06-09-pprof-doc/">go-pprof</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2021 Abel Sean<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>


  
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">

  
<script src="/fancybox/jquery.fancybox.pack.js"></script>




<script src="/js/script.js"></script>




  </div>
</body>
</html>